fn main() {
    let mut cost = String::new();
    std::io::stdin().read_line(&mut cost).unwrap();
    // shadowing
    let cost: f64 = cost.trim().parse().unwrap();
    println!("The cost is: {}", cost);

    let x = foo();
    println!("The value of x is: {}", x);

    // let x = bar();
    // print!("The value of x is: {}", x);

    // expression
    let mut x = -5;
    let y = if x > 0 { "greater" } else { "less" };
    println!("The value of y is: {}", y);

    // loop
    let z = loop {
        x += 10;
        if x > 5 {
            break x; // return value of loop
        }
    };
    println!("The value of z is: {}", z);

    // array
    let arr1 = [1, 2, 3];
    println!("The value of arr1 is: {:?}", arr1);

    let arr2 = [2; 32];
    println!("The value of arr2 is: {:?}", arr2);

    // slice must be borrowed from an array
    let slice = &arr1; // &arr1[..] also works
    println!("The value of slice is: {:?}", slice);
    let slice2 = &arr2[2..5];
    println!("The value of slice2 is: {:?}", slice2);

    // String, &str
    let s: &str = "galaxy"; // literal string is &str
    println!("The value of s is: {}", s);

    let s2: String = "galaxy".to_string(); // heap allocated string is String
    println!("The value of s2 is: {}", s2);

    let s3: String = String::from("galaxy"); // heap allocated string is String
    println!("The value of s3 is: {}", s3);

    let s4: &str = &s3; // &String can be coerced to &str
    println!("The value of s4 is: {}", s4);

    // tuple and destructuring
    let tup = (1, 2, 3);
    let (a, b, c) = tup;
    println!("The value of a is: {}", a); // 1
    println!("The value of b is: {}", b); // 2
    println!("The value of c is: {}", c); // 3

    // vector
    // let mut v = vec![1, 2, 3]; // heap allocated array
    let mut v = Vec::new();
    v.push(1);
    v.push(2);
    v.push(3);
    v.push(4);
    println!("The value of v is: {:?}", v);

    // v3 and v4 are equal
    let v3 = vec![0; 4]; // [0, 0, 0, 0]
    println!("The value of v3 is: {:?}", v3);

    // vector indexing
    let v4 = vec![1, 2, 3, 4, 5];
    let third: &i32 = &v4[2];
    println!("The value of third is: {}", third);
    let i: i8 = 2;
    let y = v4[i as usize]; // index variable must be usize
                            // as keyword is used for type casting
    println!("The value of y is: {}", y);

    // for loop
    // Loops from 0 to 9.
    for x in 0..10 {
        println!("{}", x);
    }
    let xs = [0, 1, 2, 3, 4];
    // Loop through elements in a slice of `xs`.
    for x in &xs {
        // x is a reference to the current element
        // without ownership.
        println!("{}", x);
    }

    // match expression
    let x = 5;
    match x {
        1 => println!("one"),
        2 => println!("two"),
        3 => println!("three"),
        _ => println!("anything"),
    }

    // match with binding
    // 匹配的表达式可以是任意表达式，包括元组和函数调用。
    // 构成模式 (patterns)。
    // 匹配可以绑定变量，_ 用来忽略不需要的部分。
    let x = 3;
    let y = -3;
    match (x, y) {
        (1, 1) => println!("one"),
        (2, j) => println!("two, {}", j),
        (_, 3) => println!("three"),
        (i, j) if i > 5 && j < 0 => println!("On guard!"),
        (_, _) => println!(":<"),
    }

    // {x} is a placeholder
    println!("new way to print: {x}");

    // {:x} is a placeholder for hexadecimal
    let fmted = format!("{}, {:x}, {:?}", 12, 155, Some("Hello"));
    println!("The value of fmted is: {}", fmted);
}

fn foo() -> i32 {
    42
}
